package ru.ifmo.network;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

import static ru.ifmo.network.SwingUtils.*;

/**
 * @author avhaliullin
 */
public class ConfiguratorWindow implements AppConfigurator {
    private JFrame frame;

    private int sendingPort = 1234;
    private int listeningPort = 1234;
    private String hostName = "Host " + UUID.randomUUID().toString().substring(0, 5);
    private NetworkInterface networkInterface;
    private final AtomicBoolean finished = new AtomicBoolean(false);
    private final String defaultDir = System.getProperty("user.dir");

    private final JSpinner sendingPortInput;
    private final JSpinner listeningPortInput;
    private final JTextField hostNameInput;
    private final JComboBox networkInterfaceInput;
    private final Map<String, NetworkInterface> interfaces = new HashMap<String, NetworkInterface>();
    private final JTextField directoryInput;

    private AppConfiguration configuration;

    public ConfiguratorWindow() throws SocketException {
        frame = new JFrame("Set up application:");
        sendingPortInput = new JSpinner(new SpinnerNumberModel(sendingPort, 0, 65532, 1));
        listeningPortInput = new JSpinner(new SpinnerNumberModel(listeningPort, 0, 65532, 1));

        hostNameInput = new JTextField(hostName);

        directoryInput = new JTextField(defaultDir);
        directoryInput.setEnabled(false);
        directoryInput.setDisabledTextColor(Color.black);

        final JFileChooser fileChooser = new JFileChooser(defaultDir);
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        JButton browseButton = new JButton("Browse");
        browseButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int res = fileChooser.showOpenDialog(frame);
                if (res == JFileChooser.APPROVE_OPTION) {
                    directoryInput.setText(fileChooser.getSelectedFile().getAbsolutePath());
                }
            }
        });

        for (Enumeration<NetworkInterface> interfaceIter = NetworkInterface.getNetworkInterfaces(); interfaceIter.hasMoreElements(); ) {
            NetworkInterface networkInterface = interfaceIter.nextElement();
            interfaces.put(networkInterface.getDisplayName(), networkInterface);
        }
        networkInterfaceInput = new JComboBox(new Vector<String>(interfaces.keySet()));

        JButton okButton = new JButton("Start");
        okButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                configuration = new AppConfiguration(
                        (Integer) listeningPortInput.getValue(),
                        (Integer) sendingPortInput.getValue(),
                        new File(directoryInput.getText()),
                        hostNameInput.getText(),
                        interfaces.get(networkInterfaceInput.getSelectedItem().toString()));
                frame.setVisible(false);
                synchronized (finished) {
                    finished.set(true);
                    finished.notifyAll();
                }
            }
        });

        frame.getContentPane().add(getBox(true,
                Box.createVerticalStrut(10),
                getLabeledComponent(listeningPortInput, "Listen at: "),
                Box.createVerticalStrut(10),
                getLabeledComponent(sendingPortInput, "Send to: "),
                Box.createVerticalStrut(10),
                getLabeledComponent(getBox(false, directoryInput, browseButton), "Shared folder: "),
                Box.createVerticalStrut(10),
                getLabeledComponent(hostNameInput, "Host name: "),
                Box.createVerticalStrut(10),
                getLabeledComponent(networkInterfaceInput, "Network interface: "),
                Box.createVerticalStrut(10),
                okButton,
                Box.createVerticalStrut(10)));
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                synchronized (finished) {
                    finished.set(true);
                    finished.notifyAll();
                }
            }
        });
        frame.setVisible(true);
        frame.getLayout().layoutContainer(frame);
        frame.setSize(frame.getPreferredSize().width, frame.getPreferredSize().height + frame.getHeight() - frame.getContentPane().getHeight());
    }

    public AppConfiguration getConfig() {
        finished.set(false);
        invokeLaterIfNotEDT(new Runnable() {
            public void run() {
                frame.setVisible(true);
            }
        });

        synchronized (finished) {
            while (!finished.get()) {
                try {
                    finished.wait();
                } catch (InterruptedException e) {
                    return null;
                }
            }
        }
        return configuration;
    }
}
